/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#ifndef __GimboLoaderFrame__
#define __GimboLoaderFrame__

/**
@file
Subclass of LoaderFrame, which is generated by wxFormBuilder.
*/

#include "Gimbo_forms.h"

#include "Browser.hpp"
#include "Loader.hpp"
#include "datatypedefinitions.h"
#include "thread.hpp"
#include "sync.hpp"
#include "GimboSettings.hpp"

//create custom eventtype that updater thread will use to inform gui
BEGIN_DECLARE_EVENT_TYPES()
DECLARE_EVENT_TYPE(MY_EVT_UPDATE_TREECTRLS, -1)
DECLARE_EVENT_TYPE(MY_EVT_COMPONENT_TERMINATED, -1)
END_DECLARE_EVENT_TYPES()

//defines for different variables
//these should be replaced with settings-based values

//service discovery
#define SD_TIMEOUT_SHORT 1000
#define SD_TIMEOUT_LONG 5000

namespace MaCI
{
  namespace Gimbo
  {
    class CGimboClient;
  }
}

namespace gimi
{
  class GIMI;
}

struct TTreeItemInfo
{
  wxTreeItemId clientsTreeId;
  wxTreeItemId typesTreeId;
  wxTreeItemId locationsTreeId;
  wxTreeItemId MaCITreeId;
  wxTreeItemId SessionTreeId;
};

struct TRunningTreeItemInfo
{
  wxTreeItemId runningTreeId;
};

class CServiceTreeItemData : public wxTreeItemData
{
  public:
    CServiceTreeItemData(Gimbo::TServiceContainer *service)
    :service(service)
    {}
    ~CServiceTreeItemData(){}
    
    Gimbo::TServiceContainer *service;
};

class CMaCITreeItemData : public wxTreeItemData
{
  public:
    CMaCITreeItemData(Gimbo::TMaCIServiceContainer *service)
  :service(service)
    {}
    ~CMaCITreeItemData(){}
    
    Gimbo::TMaCIServiceContainer *service;
};

class CAvailableComponentTreeItemData : public wxTreeItemData
{
  public:
    CAvailableComponentTreeItemData(Gimbo::TComponentDescriptor *component)
    :component(component){}
    ~CAvailableComponentTreeItemData(){}
    
    Gimbo::TComponentDescriptor *component;
};

class CRunningComponentTreeItemData : public wxTreeItemData
{
  public:
    CRunningComponentTreeItemData(Gimbo::TComponentInstance *component)
    :component(component){}
    ~CRunningComponentTreeItemData(){}
    
    Gimbo::TComponentInstance *component;
};

/** Implementing LoaderFrame */
class GimboLoaderFrame : public LoaderFrame, public gim::CSync, public gim::CThread, 
public Gimbo::CLoaderCallback
{
  DECLARE_EVENT_TABLE()
  
  
protected:
	// Handlers for LoaderFrame events.
	void OnClose( wxCloseEvent& event );
  void OnServiceSelectChanging( wxTreeEvent& event );
  void OnSessionSelected( wxTreeEvent& event );
  void OnStartOnlineSession( wxCommandEvent& event );
  void OnUploadSession( wxCommandEvent& event );
  void OnServiceSelectChanged( wxTreeEvent& event );
  void OnAvailableComponentActivated( wxTreeEvent& event );
  void OnAvailableComponentSelectChanging( wxTreeEvent& event );
  void OnAvailableComponentSelectChanged( wxTreeEvent& event );
  void OnRunningComponentSelectChanged( wxTreeEvent& event );
  void OnRunningComponentSelectChanging( wxTreeEvent& event );
  void OnComponentTerminate( wxCommandEvent& event );
  void OnAssignServices( wxCommandEvent& event );
  void OnConnect( wxCommandEvent& event );
	void OnPing( wxCommandEvent& event );
	
	void OnUpdate( wxCommandEvent& event );
	void OnLoadComponent( wxCommandEvent& event );
	void OnLoadSession( wxCommandEvent& event );
  void OnSaveSession( wxCommandEvent& event );
  void OnSettings( wxCommandEvent& event );
	void OnExit( wxCommandEvent& event );
	
  //handlers for custom events
  void OnUpdateTreeCtrls(wxCommandEvent& event);
  void OnComponentTerminatedWX(wxCommandEvent& event);
  void OnSettingsChanged(wxCommandEvent& event);
  
  //handlers for Loader events
  void OnComponentTerminated(Gimbo::TComponentInstance *instance);
  void OnComponentReport(Gimbo::TComponentInstance *instance);
  void OnAssignmentFailed(Gimbo::TComponentInstance *instance, 
                                  const Gimbo::TServiceAssignmentList &services);
  
public:
	/** Constructor */
	GimboLoaderFrame( wxWindow* parent );
  
  ~GimboLoaderFrame();
  
  int Connect(std::string aHub, int aPort, std::string aName);
  void Disconnect();
  
  
  
  Gimbo::CBrowser Browser;
  Gimbo::CLoader Loader;
  
private:
  const int browserMutex;
  const int currentMaciListMutex;
  gimi::GIMI *gimiPtr;
  MaCI::MaCICtrl::CMaCICtrlClient *MaCIClient;
  MaCI::Gimbo::CGimboClient *GimboClient;
  std::ostream *log;
  
  Gimbo::TClientMap* clients;
  Gimbo::TTypeMap* types;
  Gimbo::TMaCIGroupMap* MaCIGroups;
  
  Gimbo::TServiceContainerMap selectedServices;
  std::vector<Gimbo::TMaCIServiceContainer*> selectedMaCIServices;
  Gimbo::TComponentDescriptor *selectedAvailableComponent;
  Gimbo::TComponentInstance *selectedRunningComponent;
  
  wxTreeItemId runningRoot;
  
  const Gimbo::TDescriptorList *componentDescriptions;
  
  gimi::DataTypeDefinitions definitions;
  
  TGimboSettings settings;
  
  //needed for loading sessions
  MaCI::MaCICtrl::TServiceEntryArray currentMaciList;
  
  std::vector<MaCI::Gimbo::CGimboClient*> sessionClients;
  
  int ThreadFunction(const int aThreadNumber);
  
  void quit();
  void pruneOfflineServicesAndSetUserData(bool cleanAll=false);
  void updateClientsTreeCtrl();
  void updateTypesTreeCtrl();
  void updateLocationsTreeCtrl();
  void updateMaCITreeCtrl();
  void update();
  void refreshUI();
  void loadComponentDescriptions();
  void getSelectedServices(Gimbo::TServiceContainerMap &map, std::vector<Gimbo::TMaCIServiceContainer*> &MaCIList);
  void getChildrensData(Gimbo::TServiceContainerMap &map, wxTreeCtrl *tree, 
                        wxTreeItemId item);
  void getChildrensDataMaCI(std::vector<Gimbo::TMaCIServiceContainer*> &list, wxTreeItemId item);
  void assignSelectedServices(Gimbo::TComponentInstance *i);
  void loadComponent();
  void loadSettings();
  void saveSettings();
  void addToRunningTree(Gimbo::TComponentInstance *i);
  
  void addToSessionTree();
  void removeFromSessionTree();
  
};

#endif // __GimboLoaderFrame__
